Redesign listing cards around the image's real aspect ratio - #113
Conversation
Feed cells were locked to a 4:3 box, so tall and square photos were cropped to whatever fit. `CachedImageView` now reports the decoded image's aspect ratio back to its caller, and `ProductGalleryCell` sizes the image from it — falling back to 4:3 only while loading. Cells are wider (46pt of chrome instead of 68) and the column gap tightened to match. The cell also gains the information the old one dropped: category and condition under the title, and a bookmark toggle that saves without opening the listing. `loadSavedState()` only asks the server about a single post while `HomeViewModel.savedItems` hasn't loaded yet. `savedItems` holds every saved post, so once it has arrived, absence is a real answer — the naive version fired one `/post/isSaved` request per visible cell on every scroll. That needed `hasLoadedSavedItems` on `HomeViewModel` to distinguish "not saved" from "not known yet". `CategoriesView` is extracted as its own component: the Shop By Category row is about to be used by Explore, and it is the same row Home already shows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017R8mua9xepzF3mnRETtd6W
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…rimitives' into user/andrewgao/feature/UI-UX-Lucid-Refactor-03-listing-cards
CLAUDE.md keeps views to rendering and puts side effects behind the ViewModel, but ProductGalleryCell was calling NetworkManager itself to check, save and unsave posts. - Add HomeViewModel.isPostSaved(_:) and setSaved(_:for:) and have the cell call those; the "only ask the backend before savedItems loads" rule now lives with the data it depends on. - Replace the Combine onReceive($savedItems) with onChange, and load the saved state with .task(id:) instead of onAppear + Task. - Split the cell into imageButton / soldOverlay sub-views under the conventional MARK sections, and take the "Item Sold" font and colors from Constants instead of an inline Rubik-Medium 16 and .white/.black. - CategoriesView: read Constants.productCategories, make the router private, extract categoryButton(for:), and add a doc comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Feed cells were locked to a 4:3 box, so tall and square photos were cropped to
whatever fit.
CachedImageViewnow reports the decoded image's aspect ratioback to its caller, and
ProductGalleryCellsizes the image from it — fallingback to 4:3 only while loading. Cells are wider (46pt of chrome instead of 68)
and the column gap tightened to match.
The cell also gains the information the old one dropped: category and condition
under the title, and a bookmark toggle that saves without opening the listing.
loadSavedState()only asks the server about a single post whileHomeViewModel.savedItemshasn't loaded yet.savedItemsholds every savedpost, so once it has arrived, absence is a real answer — the naive version fired
one
/post/isSavedrequest per visible cell on every scroll. That neededhasLoadedSavedItemsonHomeViewModelto distinguish "not saved" from"not known yet".
CategoriesViewis extracted as its own component: the Shop By Category row isabout to be used by Explore, and it is the same row Home already shows.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_017R8mua9xepzF3mnRETtd6W